package org.jsola.hr.service.impl;

import com.alibaba.fastjson.JSON;
import org.jsola.common.StrKit;
import org.jsola.core.Page;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.common.oneKeyPay.VXpayClear;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.IVxCheckFaceDAO;
import org.jsola.hr.dto.VxCheckFaceAddDTO;
import org.jsola.hr.dto.VxCheckFaceUpdateDTO;
import org.jsola.hr.entity.EmpInfoDO;
import org.jsola.hr.entity.VxCheckFaceDO;
import org.jsola.hr.provider.IUserProviderService;
import org.jsola.hr.query.VxCheckFaceQuery;
import org.jsola.hr.service.IEmpInfoService;
import org.jsola.hr.service.ITransferAccountsBatchService;
import org.jsola.hr.service.IVxCheckFaceService;
import org.jsola.hr.vo.VxCheckFaceListVO;
import org.jsola.hr.vo.VxCheckFaceVO;
import org.jsola.hr.vo.payWx.VxConfigVO;
import org.jsola.hr.vo.payWx.checkFace.VxCheckFaceOrderVO;
import org.jsola.hr.vo.payWx.checkFace.VxCheckFaceReturnVO;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 微信人脸核身
 *
 * @author zhr
 */
@Service("hrVxCheckFaceServiceImpl")
public class VxCheckFaceServiceImpl implements IVxCheckFaceService {

    @Autowired
    private IVxCheckFaceDAO vxCheckFaceDAO;
    @Autowired
    private ITransferAccountsBatchService transferAccountsBatchService;
    @Autowired
    private IEmpInfoService empInfoService;

    @Autowired
    private IUserProviderService userProviderService;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public VxCheckFaceVO save(VxCheckFaceAddDTO vxCheckFaceAddDTO, TokenUser tokenUser) {
        // 转DO
        VxCheckFaceDO vxCheckFaceDO = vxCheckFaceAddDTO.to(VxCheckFaceDO.class);
        // 保存
        vxCheckFaceDO = save(vxCheckFaceDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return vxCheckFaceDO.to(VxCheckFaceVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(VxCheckFaceUpdateDTO vxCheckFaceUpdateDTO, TokenUser tokenUser) {
        //转DO
        VxCheckFaceDO vxCheckFaceDO = vxCheckFaceUpdateDTO.to(VxCheckFaceDO.class);
        //根据主键更新，只更新非null值
        return updateByIdSelective(vxCheckFaceDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... vxCheckFaceIds) {
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) vxCheckFaceIds);
    }


    @Override
    public VxCheckFaceVO selectById(String vxCheckFaceId, String siteId) {
        VxCheckFaceDO vxCheckFaceDO = selectDOById(vxCheckFaceId, siteId);
        if (vxCheckFaceDO == null) {
            return null;
        }
        return vxCheckFaceDO.to(VxCheckFaceVO.class);
    }

    @Override
    public List<VxCheckFaceListVO> select(VxCheckFaceQuery vxCheckFaceQuery, String siteId) {
        List<VxCheckFaceDO> vxCheckFaceDOList = selectDO(vxCheckFaceQuery, siteId);
        if(CollectionUtils.isEmpty(vxCheckFaceDOList)) {
            return vxCheckFaceDOList == null ? null : new ArrayList<>();
        }
        return vxCheckFaceDOList.stream()
                .map(vxCheckFaceDO -> vxCheckFaceDO.to(VxCheckFaceListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(VxCheckFaceQuery vxCheckFaceQuery, String siteId) {
        Example example = buildExample(vxCheckFaceQuery,siteId);
        return vxCheckFaceDAO.selectCountByExample(example);
    }

    @Override
    public Page<VxCheckFaceListVO> selectPage(VxCheckFaceQuery vxCheckFaceQuery, String siteId) {
        Example example = buildExample(vxCheckFaceQuery,siteId);
        Page<VxCheckFaceDO> page = vxCheckFaceDAO.selectPageByExample(example,
                vxCheckFaceQuery.getPageNo(),
                vxCheckFaceQuery.getPageSize());

        return page.to(VxCheckFaceListVO.class);
    }

    @Override
    public VxCheckFaceDO selectDOById(String vxCheckFaceId, String siteId) {
        return listById(vxCheckFaceId, siteId);
    }

    @Override
    public List<VxCheckFaceDO> selectDO(VxCheckFaceQuery vxCheckFaceQuery, String siteId) {
        Example example = buildExample(vxCheckFaceQuery,siteId);
        return vxCheckFaceDAO.selectByExample(example);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public VxCheckFaceVO startCheckFace(VxCheckFaceAddDTO vxCheckFaceAddDTO, TokenUser tokenUser) {
        String userName = vxCheckFaceAddDTO.getUserName();
        String idCardNumber = vxCheckFaceAddDTO.getIdCardNumber();
        if (StrKit.isEmpty(userName) || StrKit.isEmpty(idCardNumber)) {
            throw new ParamException("用户实名和用户证件号都不能为空");
        }
        // 获取微信服务商全部的配置信息
        VxConfigVO vxConfigVO = transferAccountsBatchService.selectVxConfigVO(tokenUser.getSiteId());
        if (StrKit.isEmpty(vxConfigVO.getSubMchid())) {
            // 没有配置默认使用京普科技的特约商户号
            vxConfigVO.setSubMchid("1615112360");
        }
        // openId
        String openId = userProviderService.selectOpenIdByUserIdAndAppId(tokenUser.getUserId(),
                vxConfigVO.getSpAppidXCX(), tokenUser);
        if (StrKit.isEmpty(openId)) {
            throw new ParamException("根据appid没有找到当前用户对应的openId，请重新登录授权或联系管理员！");
        }
        // 生成ID
        String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
        // 设置固定的值
        String projectName = "职薪人";
        String employerName = "京普科技";
        String employmentType = "LONG_TERM_EMPLOYMENT";
        // 设置body的值
        VxCheckFaceOrderVO vxCheckFaceOrderVO = new VxCheckFaceOrderVO();
        vxCheckFaceOrderVO.setOpenid(openId);
        vxCheckFaceOrderVO.setAppid(vxConfigVO.getSpAppidXCX());
        vxCheckFaceOrderVO.setSubMchid(vxConfigVO.getSubMchid());
        vxCheckFaceOrderVO.setAuthenticateNumber(uuid);
        vxCheckFaceOrderVO.setUserName(VXpayClear.rsaEncryptOAEP(userName, vxConfigVO.getVxCertificate()));
        vxCheckFaceOrderVO.setIdCardNumber(VXpayClear.rsaEncryptOAEP(idCardNumber, vxConfigVO.getVxCertificate()));
        vxCheckFaceOrderVO.setProjectName(projectName);
        vxCheckFaceOrderVO.setEmployerName(employerName);
        vxCheckFaceOrderVO.setEmploymentType(employmentType);
        // 调用微信人脸核身
        String authorization = VXpayClear.generateAuthorization(JSON.toJSONString(vxCheckFaceOrderVO), "POST",
                "https://api.mch.weixin.qq.com/v3/payroll-card/authentications/pre-order-with-auth",
                vxConfigVO.getSpMchid(), vxConfigVO.getCertificateSerialNo(), vxConfigVO.getPrivateKeyPath());
        VxCheckFaceReturnVO vxCheckFaceReturnVO = VXpayClear.vxCheckFace(vxCheckFaceOrderVO, authorization,
                vxConfigVO.getWechatpaySerial());
        // 保存
        VxCheckFaceDO vxCheckFaceDO = new VxCheckFaceDO();
        vxCheckFaceDO.setUserId(tokenUser.getUserId());
        vxCheckFaceDO.setOpenid(openId);
        vxCheckFaceDO.setAppid(vxConfigVO.getSpAppidXCX());
        vxCheckFaceDO.setSubMchid(vxConfigVO.getSubMchid());
        vxCheckFaceDO.setId(uuid);
        vxCheckFaceDO.setUserName(userName);
        vxCheckFaceDO.setIdCardNumber(idCardNumber);
        vxCheckFaceDO.setProjectName(projectName);
        vxCheckFaceDO.setEmployerName(employerName);
        vxCheckFaceDO.setEmploymentType(employmentType);
        vxCheckFaceDO.setToken(vxCheckFaceReturnVO.getToken());
        vxCheckFaceDO.setMchid(vxConfigVO.getSpMchid());
        vxCheckFaceDO = save(vxCheckFaceDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return vxCheckFaceDO.to(VxCheckFaceVO.class);
    }

    @Override
    public VxCheckFaceVO startCheckFaceByCompanyId(String companyId, TokenUser tokenUser) {
        EmpInfoDO empInfoDO = empInfoService.selectByUserIdAndCompanyId(tokenUser.getUserId(), companyId);
        ParamException.notNull(empInfoDO, "根据用工单位信息没有找到对应的花名册信息，请联系管理员添加您到该用工单位花名册中");
        if (StrKit.isEmpty(empInfoDO.getName()) || StrKit.isEmpty(empInfoDO.getIdCard())) {
            throw new ParamException("花名册信息不完整，缺少姓名或身份证号，请完善信息后重试！");
        }
        VxCheckFaceAddDTO vxCheckFaceAddDTO = new VxCheckFaceAddDTO();
        vxCheckFaceAddDTO.setUserName(empInfoDO.getName());
        vxCheckFaceAddDTO.setIdCardNumber(empInfoDO.getIdCard());
        return  this.startCheckFace(vxCheckFaceAddDTO, tokenUser);
    }


    /**
     * 根据查询参数，构建example

     * @param vxCheckFaceQuery 查询参数
     * @param siteId 所属站点id
     * @return example
     */
    private Example buildExample(VxCheckFaceQuery vxCheckFaceQuery, String siteId) {
        Example example = new Example(VxCheckFaceDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (vxCheckFaceQuery.getUserId() != null) {
            example.and().andEqualTo("userId", vxCheckFaceQuery.getUserId());
        }
        if (vxCheckFaceQuery.getOpenid() != null) {
            example.and().andEqualTo("openid", vxCheckFaceQuery.getOpenid());
        }
        // 排序
        ExampleKit.setExampleOrder(example,vxCheckFaceQuery.getOrders());
        return example;
    }
}




